﻿using System;
using System.Collections.Generic;

namespace Keeton.Core
{
    public class HtmlNodeComparer : IFuzzyComparer<HtmlNode>
    {
        public HtmlNodeComparer()
        {
            this.AttributeComparer = new HtmlAttributeComparer();
            this.ContentComparer = new HtmlContentComparer();
            this.WeightStrategy = new HtmlWeightStrategy();
            this.ComparisonStrategy = new HtmlComparisonStrategy();
        }

        public IFuzzyComparer<HtmlAttribute> AttributeComparer { get; private set; }

        public IFuzzyComparer<HtmlContent> ContentComparer { get; private set; }

        public HtmlWeightStrategy WeightStrategy { get; private set; }

        public HtmlComparisonStrategy ComparisonStrategy { get; private set; }

        public decimal Compare(HtmlNode leftNode, HtmlNode rightNode)
        {
            var leftAttributes = leftNode.Attributes;
            var rightAttributes = rightNode.Attributes;

            var leftContent = leftNode.Content;
            var rightContent = rightNode.Content;

            var leftChildren = leftNode.Children;
            var rightChildren = rightNode.Children;

            var attributesSimilarity = this.AttributeComparer.Compare(leftAttributes, rightAttributes);
            var contentSimilarity = this.ContentComparer.Compare(leftContent, rightContent);
            var childrenSimilarity = this.Compare(leftChildren, rightChildren);

            var leftWeights = this.WeightStrategy.GetWeights(leftAttributes, leftContent, leftChildren);
            var rightWeights = this.WeightStrategy.GetWeights(rightAttributes, rightContent, rightChildren);

            var attributesWeight = (leftWeights[leftAttributes] + rightWeights[rightAttributes]) / 2;
            var contentWeight = (leftWeights[leftContent] + rightWeights[rightContent]) / 2;
            var childrenWeight = (leftWeights[leftChildren] + rightWeights[rightChildren]) / 2;

            var similarity = attributesSimilarity * attributesWeight + contentSimilarity * contentWeight + childrenSimilarity * childrenWeight;

            return similarity;

        }

        public decimal Compare(IEnumerable<HtmlNode> left, IEnumerable<HtmlNode> right)
        {
            var similarity = this.ComparisonStrategy.Compare(left, right, this);

            return similarity;
        }
    }
}
